﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using Soat.SoPrism.TemplateWizards.Properties;

namespace Soat.SoPrism.TemplateWizards.Helpers
{
    /// <summary>
    /// Cette classe contient l'ensemble des outils permettant de gérer l'Environnement de Visual Studio
    /// </summary>
    internal class EnvDTEHelper
    {
        #region GetTargetSolutionFolder Method

        /// <summary>
        /// Méthode permettant de récupérer le répertoire de la solution
        /// en passant par la recherche d'un projet projet (extension .csproj)
        /// et en remontant l'ensembles des répertoire...
        /// </summary>
        /// <param name="solution"></param>
        /// <returns></returns>
        public string GetTargetSolutionFolder(SolutionClass solution)
        {
            // Copie des fichiers
            Project csProj = this.GetTargetProject(solution, Resources.CSPROJ);
            return csProj.FileName.Replace((csProj).UniqueName.Remove(0, (csProj).UniqueName.IndexOf('\\')), "");
        } 

        #endregion

        #region GetReferencesProject Method

        /// <summary>
        /// Cette méthode permet de récupére l'objet répertoire de solution "_References"
        /// </summary>
        /// <param name="solution">Objet Solution</param>
        /// <returns>Objet Solution Folder</returns>
        public Project GetReferencesProject(SolutionClass solution)
        {
            Project result = null;
            for (int i = 1; i <= solution.Projects.Count; i++)
            {
                var currentProj = solution.Projects.Item(i);
                if (currentProj.Name.Equals(Resources.REFERENCE_SOLUTION_FOLDER, StringComparison.InvariantCultureIgnoreCase))
                {
                    result = currentProj;
                    break;
                }
            }
            return result;
        } 

        #endregion

        #region GetTargetProject Method

        /// <summary>
        /// Cette méthode permet de récupérer un objet projet à partir d'un filtre (nom se terminant par filter)
        /// Autre que "_References". Parcours récursif
        /// </summary>
        /// <param name="solution">Objet Solution</param>
        /// <param name="filter">Partie du nom d'un projet à rechercher</param>
        /// <returns>Objet Projet trouvé</returns>
        public Project GetTargetProject(SolutionClass solution, string filter)
        {
            Project csProj = null;
            for (int i = 1; i <= solution.Projects.Count; i++)
            {
                if (!solution.Projects.Item(i).Name.Equals(Resources.REFERENCE_SOLUTION_FOLDER, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (this.RecursiveProjectParse(solution.Projects.Item(i), filter, out csProj))
                    {
                        break;
                    }
                }

            }
            return csProj;
        }

        /// <summary>
        /// Recherche d'un Project de type .csproj de manière récursive
        /// </summary>
        /// <param name="proj">Objet Projet Parent</param>
        /// <param name="firstCSProj">Premier Objet Projet trouvé</param>
        /// <returns>Vrai si Trouvé</returns>
        private bool RecursiveProjectParse(Project proj, string filter, out Project firstCSProj)
        {
            firstCSProj = null;
            var result = false;
            if (proj != null)
            {
                result = Convert.ToString(proj.FileName).EndsWith(filter, StringComparison.InvariantCultureIgnoreCase);
                if (!result)
                {
                    // Parcours des sous projets
                    for (int i = 1; i <= proj.ProjectItems.Count; i++)
                    {
                        result = this.RecursiveProjectParse(proj.ProjectItems.Item(i).SubProject, filter, out firstCSProj);
                        if (result)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    firstCSProj = proj;
                }
            }
            return result;
        } 

        #endregion

        #region FindHierarchyItem Methods

        internal EnvDTE.UIHierarchyItem FindHierarchyItem(EnvDTE.UIHierarchyItems items, EnvDTE.ProjectItem p)
        {
            if (items == null)
                return null;

            foreach (EnvDTE.UIHierarchyItem item in items)
            {
                if (item.Object == p)
                    return item;
                EnvDTE.UIHierarchyItem result = FindHierarchyItem(item.UIHierarchyItems, p);
                if (result != null)
                    return result;
            }
            return null;
        }

        internal EnvDTE.UIHierarchyItem FindHierarchyItem(EnvDTE.UIHierarchyItems items, EnvDTE.Project p)
        {
            if (items == null)
                return null;

            foreach (EnvDTE.UIHierarchyItem item in items)
            {
                if (item.Object == p)
                    return item;
                EnvDTE.UIHierarchyItem result = FindHierarchyItem(item.UIHierarchyItems, p);
                if (result != null)
                    return result;
            }
            return null;
        } 

        #endregion

    }
}
